#include "VibTerrainFileManager.h"
#include <iostream>
#include <iomanip>
#include <fstream>

#include "../util/Tokenizer.h"
#include "../geom/TerrainModel.h"

using namespace dataengine;

VibTerrainFileManager::VibTerrainFileManager(std::string filename) : TerrainFileManager(filename)
{
}

VibTerrainFileManager::~VibTerrainFileManager()
{
}

bool VibTerrainFileManager::canLoadFile()
{
	try
	{
		if(m_tok.get() == NULL)
			m_tok.reset(new util::Tokenizer(m_filename));
		m_tok->rewind();
		if(m_tok->getNextWord() != "VIBOSTERRAIN" || m_tok->getNextWord() != "VERSION" || m_tok->getNextWord() != "100")
			return false;
		return true;
	}
	catch(...)
	{
		return false;
	}
}

geom::TerrainModel VibTerrainFileManager::loadFile()
{
	geom::TerrainModel result;
	if(m_tok.get() == NULL)
		m_tok.reset(new util::Tokenizer(m_filename));
	m_tok->rewind();
	m_tok->checkToken("VIBOSTERRAIN", m_tok->getNextWord());
	m_tok->checkToken("VERSION", m_tok->getNextWord());
	m_tok->checkToken("100", m_tok->getNextWord());

	int numHorizonValues = 0;

	string tokens[5]={"HORIZONVALUES","TRI","P"};	
	while(true)
	{
		string currentToken = m_tok->getNextWord();
		if(m_tok->eof())
			break;

		int tokenID=-1;
		for(int i=0;i<3;i++)
			if(currentToken == tokens[i])
				tokenID = i;

		if(tokenID == -1)
			throw DataException("Token "+currentToken+" could not be interpreted as part of a terrain file");

		switch(tokenID)
		{
			case 0: {// HORIZONVALUES
						numHorizonValues = (int) m_tok->getNextFloat();
						if(numHorizonValues != geom::NUM_HORIZON_SPLITS)
							throw DataException("Number of horizon values in file is not what the program is ready to accept");
					}break;
			case 1: {// TRI
						// We read the triangle 3 values
                        geom::IntTri tri;
						tri[0] = (int) m_tok->getNextFloat();
						tri[1] = (int) m_tok->getNextFloat();
						tri[2] = (int) m_tok->getNextFloat();
						result.addTriangle(tri);
					}break;
			case 2: {// P(oint)
						// We read the point data
						util::Triplet<float> p;
                        geom::TerrainPoint po ;
						m_tok->readNextFloatTriplet(p);
						po.p = geom::Point3D(&(p[0]));
						m_tok->checkToken("N", m_tok->getNextWord());
						m_tok->readNextFloatTriplet(p);
						po.n = geom::Vector3D(&(p[0]));
						m_tok->checkToken("H", m_tok->getNextWord());
						for(int i=0;i<geom::NUM_HORIZON_SPLITS;++i)
							po.horizonValues[i] = m_tok->getNextFloat();
						result.addPoint(po); 
					}break;
			default:
					throw DataException("Found a nonenxistent token type THIS SHOULD NEVER HAPPEN!\n");
		}
	}
	return result;
}

void VibTerrainFileManager::saveToFile(const geom::TerrainModel &ob) 
{
	if(ob.getNumberOfPoints() == 0)
		return;

	ofstream file;
	file.open (m_filename.c_str());
	if(file.fail())
		return;

	file << "VIBOSTERRAIN VERSION 100\n";
	file << "HORIZONVALUES " << geom::NUM_HORIZON_SPLITS<<"\n";
    geom::TerrainPointsList::const_iterator it = ob.points().begin();
    geom::TerrainPointsList::const_iterator end = ob.points().end();
	for(;it!=end;++it)
    {
        file<<"P "<<it->p.x<<" "<<it->p.y<<" "<<it->p.z<<" "<<" N "<<it->n.dx<<" "<<it->n.dy<<" "<<it->n.dz<<" H";
        for(int i=0;i<geom::NUM_HORIZON_SPLITS;++i)
            file<<" "<<it->horizonValues[i];
        file<<"\n";
    }

    geom::TrisList::const_iterator trit = ob.triangles().begin();
    geom::TrisList::const_iterator trend = ob.triangles().end();
	int trisCounter = 0;
	for(;trit!=trend;++trit,++trisCounter)
	{
		file<<"TRI "<< (*trit)[0]<<" "<<(*trit)[1]<<" "<<(*trit)[2]<<" ";
		if(trisCounter%4==3)
			file<<"\n";
	}
	file.flush();
	file.close();
}

